package la.iok.hzsvn.lewin.movie.cloud.service;

import la.iok.hzsvn.lewin.movie.cloud.entity.OrgUnit;
import la.iok.hzsvn.lewin.movie.cloud.model.OrgUnitGeo;
import la.iok.hzsvn.lewin.movie.cloud.model.OrgUnitParam;
import la.iok.hzsvn.lewin.movie.cloud.model.OrgUnitVo;
import la.iok.hzsvn.lewin.movie.core.Token;
import la.iok.hzsvn.lewin.movie.core.model.OrgUnitType;
import la.iok.hzsvn.lewin.movie.core.model.SimpleOrgUnitVo;
import la.iok.hzsvn.lewin.mybatis.model.PageVo;
import la.iok.hzsvn.lewin.mybatis.service.BaseService;
import la.iok.hzsvn.share.annotations.NotNull;
import la.iok.hzsvn.share.annotations.NotNullElement;
import la.iok.hzsvn.share.annotations.NullElement;
import la.iok.hzsvn.share.annotations.Nullable;

import java.util.Collection;
import java.util.List;

public interface OrgUnitService extends BaseService<OrgUnit,Long> {
    /**
     * 保存组织
     * @param orgUnit 组织参数
     * @param token 操作用户
     * @return 新添加的组织的id
     */
    Long save(@NotNull OrgUnitParam orgUnit, @NotNull Token token);

    /**
     * 验证权限并删除记录
     * @param id 组织id
     * @param token 操作用户
     */
    void delete(@Nullable Long id, @NotNull Token token);

    /**
     * 更新组织，只能更新名称和地址
     * @param token 操作用户
     * @param orgUnitId 组织id
     * @param orgUnitParam 组织信息
     */
    void update(@NotNull Token token, @Nullable Long orgUnitId, @Nullable OrgUnitParam orgUnitParam);

    /**
     * 分页查询组织
     * @param page 页号,从1开始
     * @param limit 分布大小
     * @param type 组织类型
     * @param name 组织名称,模糊查询
     * @param parentId 父组织id.查询结果包含此组织
     * @return 当前分页信息
     */
    PageVo<OrgUnitVo> page(int page, int limit, Integer type, String name,Long parentId);

    /**
     * 批量查询组织
     * @param orgUnitIds 组织id集合
     * @return 组织列表
     */
    @NotNull
    @NotNullElement
    List<OrgUnit> list(@Nullable @NullElement Collection<Long> orgUnitIds);

    /**
     * 在所有组织中查询对应类型的组织数量
     * @param type 组织类型.值为{@link OrgUnitType#getCode()}
     * @return 数量
     */
    int count(@Nullable Integer type);

    /**
     * 查询特定组织（包括此组织）下,对应类型的组织。
     * @param orgUnitId 组织的限制范围,表示组织本身和它管理的所有其他组织
     * @param type 需要返回数量的组织类型
     * @return 组织数量
     */
    int count(@Nullable Long orgUnitId, @Nullable Integer type);

    /**
     * 在特定组织下,查询指定组织及其管理的其他组织的总数量
     * @param parentId 所有组织的父组织。限制查询只在此组织及其管理的组织下
     * @param orgUnitId 待查询的组织,可能为null,为null表示不限制查询特定组织
     * @param type 组织类型
     * @return 组织数量
     */
    int count(@NotNull Long parentId, @Nullable Long orgUnitId, @Nullable Integer type);

    /**
     * 所有子组织的id.只包含直接儿子组织,不包括自己及儿子以下的组织
     * @param parentId 父组织id
     * @return 子组织id列表
     */
    @NotNull
    @NotNullElement
    List<Long> childOrgUnitIds(@Nullable Long parentId);

    @NotNull
    @NotNullElement
    List<Long> childOrgUnitIds(@Nullable Long[] parentIds);

    /**
     * 组织信息
     * @param id 组织id
     * @return 组织信息
     */
    @Nullable
    SimpleOrgUnitVo simple(@Nullable Long id);

    /**
     * 组织信息
     * @param ids 组织id列表
     * @return
     */
    @NotNull
    @NotNullElement
    List<SimpleOrgUnitVo> simple(@Nullable Long[] ids);

    void online(@NotNull Token token, @Nullable Long id);

    void offline(@NotNull Token token, @Nullable Long id);

    /**
     * 在redis构建店铺的地理坐标信息。此处会删除redis中原来的内容并重新读取数据库中的店铺位置写入redis,店铺数量多的话可能会久一些
     */
    void buildShopGeo(@NotNull Token token);

    /**
     * 根据定位搜索附近的店铺
     * @param lng 定位的经度
     * @param lat 定位的纬度
     * @return 搜索的店铺列表
     */
    List<OrgUnitGeo> geoSearch(Double lng, Double lat,Double radius);

}
